/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.screen;

import com.daikit.commons.shared.utils.DkIdGenerator;
import com.daikit.commons.shared.utils.DkObjectUtils;
import com.daikit.daikit4gxt.client.action.BaseAction;
import com.daikit.daikit4gxt.client.log.BaseLogger;
import com.daikit.daikit4gxt.client.ui.UIInvalidatable;
import com.sencha.gxt.widget.core.client.ContentPanel;


/**
 * Methods that should be overridden to provide custom mechanism :<br>
 * - {@link #onFullScreenChanged()}<br>
 * - {@link #initializeScreenSubPanel(Object...)}<br>
 * - {@link #needToBeReloaded()}<br>
 * <br>
 * You have a way to tell the order following which sub panels are reloaded using the function
 * {@link #setReloadOrder(int)}
 * 
 * @author Thibaut CASELLI
 * 
 */
public abstract class ScreenSubPanel extends ContentPanel implements Comparable<ScreenSubPanel>, UIInvalidatable
{

	protected final BaseLogger log = BaseLogger.getLog(getClass());

	private int reloadOrder = 0;

	private Screen parentScreen;

	private final String id = DkIdGenerator.generateRandomId(8);

	/**
	 * Constructor
	 */
	public ScreenSubPanel()
	{
		// Nothing done by default
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// INVALIDATE UI
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Method called by screen
	 */
	public void baseInvalidateUi()
	{
		invalidateUi();
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// ON FULL SCREEN CHANGED
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * Method to be overridden to provide custom behavior when the full screen status changed.
	 */
	public void onFullScreenChanged()
	{
		// Nothing done by default
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// RELOAD SCREEN ACTIONS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	public void initializeScreenSubPanel(final Object... optionalArgs)
	{
		// Nothing done by default
	}

	public abstract boolean needToBeReloaded();

	public abstract BaseAction<?> getReloadSubPanelAction(final boolean force, final Object... optionalArgs);

	public BaseAction<?> getEndOfReloadScreenActionForSubPanel(final boolean force, final Object... optionalArgs)
	{
		// Nothing done by default
		return null;
	}

	public final boolean isFirstReloadAfterShow()
	{
		if (getParentScreen() == null)
		{
			throw new RuntimeException("Either this ScreenSubPanel was added to a hierarchy that does not contain any "
					+ "screen or this method is calle before the ScreenSubPanel was added to its parent Screen.");
		}
		return getParentScreen().isFirstReloadAfterShow();
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// SCREEN HIERARCHY
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	// @Override
	// protected final void onRender(final Element parent, final int pos) {
	// super.onRender(parent, pos);
	// final Screen parentScreen = findParentScreen(this);
	// if (parentScreen == null) throw new
	// RuntimeException("Can't add a screen sub panel to a hierarchy that does not contain any screen.");
	// parentScreen.registerSubPanel(this);
	// }
	//
	// private final Screen findParentScreen(final Widget widget) {
	// if (widget == null) return null;
	// final Widget parent = widget.getParent();
	// if (parent == null || widget.equals(parent)) return null;
	// if (widget instanceof Screen) return (Screen) widget;
	// return findParentScreen(parent);
	// }

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// GETTERS / SETTERS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	public final int getReloadOrder()
	{
		return reloadOrder;
	}

	public Screen getParentScreen()
	{
		return parentScreen;
	}

	public void setParentScreen(final Screen parentScreen)
	{
		this.parentScreen = parentScreen;
	}

	public final void setReloadOrder(final int reloadOrder)
	{
		this.reloadOrder = reloadOrder;
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// UTILS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	@Override
	public final int compareTo(final ScreenSubPanel o)
	{
		if (o == null)
		{
			return 1;
		}
		if (reloadOrder == o.reloadOrder)
		{
			return 0;
		}
		if (reloadOrder < o.reloadOrder)
		{
			return -1;
		}
		return 1;
	}

	/**
	 * @param fill
	 *           to fill background color with them specific color
	 */
	public void setFillBackgroundColor(final boolean fill)
	{
		if (fill)
		{
			addStyleName("fill-background-color");
			removeStyleName("cancel-fill-background-color");
		}
		else
		{
			removeStyleName("fill-background-color");
			addStyleName("cancel-fill-background-color");
		}
	}

	@Override
	public boolean equals(final Object obj)
	{
		return obj instanceof ScreenSubPanel && DkObjectUtils.equalsWithNull(id, ((ScreenSubPanel) obj).id);
	}

	@Override
	public int hashCode()
	{
		return id.hashCode();
	}
}
